package org.stars.dao.loader;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.stars.dao.config.MacroPath;
import org.stars.dao.config.Macros;
import org.stars.dao.sqlmapper.macro.Macro;
import org.stars.dao.sqlmapper.macro.MacroBase;
import org.stars.dao.sqlmapper.macro.MacroDefinition;
import org.stars.datastructure.map.CaseInsensitiveHashMap;
import org.stars.util.reflect.AnnotationResolverUtil;

import static org.stars.config.Message.MACRO_LOADER_01;
import static org.stars.config.Message.MACRO_LOADER_02;
import static org.stars.config.Message.MACRO_LOADER_03;
import static org.stars.config.Message.MACRO_LOADER_04;

public abstract class MacroLoader {
	
	protected static Log log=LogFactory.getLog(MacroLoader.class);
	
	public static Map<String, Macro> load(Macros macros)
	{		
		log.debug(MACRO_LOADER_01.toString());	
		AnnotationResolverUtil<MacroDefinition, Macro> util=new AnnotationResolverUtil<MacroDefinition, Macro>();
		
		List<String> packages=new LinkedList<String>();
		
		String defaultPackage=MacroBase.class.getPackage().getName();
		packages.add(defaultPackage);
		
		for(MacroPath item: macros.getList())
		{
			packages.add(item.getPackagePattern());
		}
		
		util.setPackageFilters(packages);
		util.loadImplementationsFromContextClassloader(MacroDefinition.class);

		// macro
		Set<Class<? extends Macro>> classes = util.getClasses();
		Map<String, Macro> macroMap=new CaseInsensitiveHashMap<Macro>();
		Macro macro=null;
			
		for (Class<? extends Macro> item: classes)
		{
			try {
				macro=item.newInstance();
				macroMap.put(item.getSimpleName(), macro);				
				log.debug(MACRO_LOADER_02.with(item.getSimpleName(),item.getCanonicalName()));
			} catch (Exception e) {
				log.error(MACRO_LOADER_03.with(item.getSimpleName(),item.getCanonicalName()));
			}
		}		
		log.debug(MACRO_LOADER_04.toString());
		
		return macroMap;
		
	}
	
}
